package com.example.java_gobang.api;

import com.example.java_gobang.game.MatchRequest;
import com.example.java_gobang.game.MatchResponse;
import com.example.java_gobang.game.Matcher;
import com.example.java_gobang.game.OnlineUserManager;
import com.example.java_gobang.model.User;
import com.example.java_gobang.model.UserMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.w3c.dom.Text;

//通过这个类来处理匹配功能中的 websocket 请求
@Component
public class MatchAPI extends TextWebSocketHandler {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private Matcher matcher;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //玩家上线, 加入到OnlineUserManager中

        //1.获取到当前用户的身份信息(谁在游戏大厅中, 建立的连接)
        //此处的代码, 之所以能够 getAttributes, 全靠在注册 WebSocket的时候,
        //加上的 .addInterceptors(new HttpSessionHandshakeInterceptor());
        //这个逻辑就把 HttpSession 中的 Attribute 都拿到了 WebSocketSession 中了
        //在Http登录逻辑中, 往HttpSession中存了User数据:httpSession.setAttribute("user",user);
        //此时就可以在WebSocketSession中吧之前HttpSession你存的User对象拿到了
        //注意:此处拿到的user是有可能为空的
        //如果之前用户没有通过 HTTP 来进行登录, 直接通过 /game_hall.html 这个url 来访问游戏大厅页面
        //此时就会出现user为null的情况

        try {
            User user = (User) session.getAttributes().get("user");

            //2.先判定用户是否已经登录过(已经是在线), 如果是已经在线, 就不该继续进行后续逻辑
            if(onlineUserManager.getFromGameHall(user.getUserId()) != null
            ||onlineUserManager.getFromGameRoom(user.getUserId())!=null) {
                //当前用户已经登录了
                //针对这个情况要告诉客户端, 你这里重复登录了;
                MatchResponse response = new MatchResponse();
                response.setOk(true);
                response.setReason("当前禁止多开");
                response.setMessage("repeatConnection");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                //此处直接关闭有些太激进了, 还是返回一个特殊的 message , 供客户端来处理
                //session.close();
                System.out.println("[MatchAPI]: 当前禁止多开" + " " + onlineUserManager.getFromGameHall(user.getUserId()) + " " + onlineUserManager.getFromGameRoom(user.getUserId())!=null);
                return;
            }

            //3.拿到了身份信息之后, 就可以把玩家设置成在线状态了
            onlineUserManager.enterGameHall(user.getUserId(), session);
            System.out.println("玩家 " + user.getUsername() + " 进入游戏大厅");
        }catch (NullPointerException e) {
            //e.printStackTrace();
            System.out.println("[MatchAPI.afterConnectionEstablished] 当前用户未登录!");
            //出现空指针异常, 说明当前用户的身份信息时空
            //就把当前用户尚未登录的信息返回
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setReason("您尚未登录! 不能进行后续匹配功能!");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }

    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //实现处理开始匹配请求和停止匹配请求
        User user = (User) session.getAttributes().get("user");
        //获取到客户端给服务器发送的数据
        String payload = message.getPayload();
        //当前这个数据载荷是一个JSON格式的字符串, 就需要把他转成java对象, MatchRequest
        MatchRequest request = objectMapper.readValue(payload, MatchRequest.class);
        MatchResponse response = new MatchResponse();
        if(request.getMessage().equals("startMatch")) {
            //进入匹配队列
            matcher.add(user);
            // TODO 先创建一个匹配队列, 把用户加进去
            //把玩家放进匹配队列之后, 就可以返回一个响应给客户端了
            response.setOk(true);
            response.setMessage("startMatch");
        }else if(request.getMessage().equals("stopMatch")) {
            //退出匹配队列
            matcher.remove(user);
            // TODO 先创建一个匹配队列, 把用户移除
            //移除之后, 就可以返回一个响应给客户端
            response.setOk(true);
            response.setMessage("stopMatch");
        }else {
            //非法情况
            response.setOk(false);
            response.setReason("非法的匹配请求");
        }

        String jsonString = objectMapper.writeValueAsString(response);
        session.sendMessage(new TextMessage(jsonString));
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        //玩家下线, 从OnlineUserManager中删除
        try {
            User user = (User) session.getAttributes().get("user");
            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if(tmpSession == session) {
                onlineUserManager.exitGameHall(user.getUserId());
            }
            //如果玩家正在匹配中, 而WebSocket连接断开了, 就应该移除匹配队列
            matcher.remove(user);
        }catch (NullPointerException e) {
            System.out.println("[MatchApi.handleTransportError]: 当前用户未登录!");
            //e.printStackTrace();
            //出现空指针异常, 说明当前用户的身份信息时空
            //就把当前用户尚未登录的信息返回
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setReason("您尚未登录! 不能进行后续匹配功能!");
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try {
            //玩家下线, 从OnlineUserManager中删除
            User user = (User) session.getAttributes().get("user");
            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if(tmpSession == session) {
                onlineUserManager.exitGameHall(user.getUserId());
            }
            //如果玩家正在匹配中, 而WebSocket连接断开了, 就应该移除匹配队列
            matcher.remove(user);
        }catch (NullPointerException e) {
            System.out.println("[MatchApi.afterConnectionClosed]: 当前用户未登录!");
            //e.printStackTrace();
            //出现空指针异常, 说明当前用户的身份信息时空
            //就把当前用户尚未登录的信息返回

//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setReason("您尚未登录! 不能进行后续匹配功能!");
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
    }
}
